from typing import Optional

class QTorchException(Exception):
    """量化系统基础异常"""
    def __init__(self, message: str, code: Optional[int] = None):
        self.code = code
        super().__init__(message)

class FinancialDataException(QTorchException):
    """财务数据异常基类"""
    def __init__(self, message: str, symbol: Optional[str] = None):
        super().__init__(f"[{symbol}] {message}" if symbol else message)
        self.symbol = symbol

class FinancialFieldMissing(FinancialDataException):
    """财务字段缺失异常"""
    def __init__(self, missing_fields: list, symbol: str):
        super().__init__(
            f"缺失关键财务字段: {', '.join(missing_fields)}", 
            symbol=symbol
        )

class FinancialRatioAnomaly(FinancialDataException):
    """财务比率异常"""
    def __init__(self, ratio_name: str, value: float, symbol: str):
        super().__init__(
            f"{ratio_name} 异常值: {value:.2f}", 
            symbol=symbol
        )

class DataValidationException(QTorchException):
    """数据验证异常基类"""
    pass

class GPUMemoryError(QTorchException):
    """显存不足异常"""
    def __init__(self, message: str, device_name: Optional[str] = None, usage_percent: Optional[float] = None):
        device_info = f"[{device_name}]" if device_name else ""
        usage_info = f"使用率: {usage_percent:.1%}" if usage_percent is not None else ""
        full_message = f"{device_info} {message} {usage_info}".strip()
        super().__init__(full_message)
        self.device_name = device_name
        self.usage_percent = usage_percent

class GPUOperationError(QTorchException):
    """通用GPU操作异常"""
    def __init__(self, message: str, device_name: Optional[str] = None, operation: Optional[str] = None):
        device_info = f"[{device_name}]" if device_name else ""
        op_info = f"操作: {operation}" if operation else ""
        full_message = f"{device_info} {message} {op_info}".strip()
        super().__init__(full_message)
        self.device_name = device_name
        self.operation = operation

class PrecisionConversionError(QTorchException):
    """混合精度转换异常"""
    def __init__(self, message: str, source_dtype: Optional[str] = None, target_dtype: Optional[str] = None):
        dtype_info = f"({source_dtype} -> {target_dtype})" if source_dtype and target_dtype else ""
        full_message = f"{message} {dtype_info}".strip()
        super().__init__(full_message)
        self.source_dtype = source_dtype
        self.target_dtype = target_dtype